#pragma once
#include <vector>
#include <iostream>
#include <cassert>
#include <string>
#include <cstring>
#include "log.hpp"

namespace Muduo
{
#define BUFFER_DEFAULT_SIZE 1024
    class Buffer
    {
    public:
        Buffer():_buffer(BUFFER_DEFAULT_SIZE),_reader_idx(0),_writer_idx(0){}

        //_buffer空间的起始地址
        char * Begin() 
        {
            return &(*_buffer.begin());
        }

        //获取当前写入起始位置,_buffer的空间起始地址+写偏移量
        char * WritePosition() 
        {
            return Begin()+_writer_idx;
        }

        //获取当前读取起始位置,_buffer的空间起始地址+读偏移量
        char * ReadPosition() 
        {
            return Begin()+_reader_idx;
        }

        //获取缓冲区末尾空闲空间大小,写偏移之后的空间,总体空间大小减去写偏移
        uint64_t TailIdleSize() 
        {
            return _buffer.size()-_writer_idx;
        }

        //获取缓冲区起始空闲空间大小,读偏移之前的空闲空间
        uint64_t HeadIdleSize() 
        {
            return _reader_idx;
        }

        //获取可读数据大小,写偏移-读偏移
        uint64_t ReadAbleSize() 
        {
            return _writer_idx-_reader_idx;
        }

        //将读偏移向后移动指定长度
        void MoveReadOffset(uint64_t len)
        {
            if(len == 0) return;
            //向后移动的大小,一定要小于可读数据大小
            assert(len<=ReadAbleSize());
            _reader_idx+=len;
        }

        //将写偏移向后移动指定长度
        void MoveWriteOffset(uint64_t len)
        {
            //向后移动的带下,必须小于当前末尾空闲空间的大小
            assert(len<=TailIdleSize());
            _writer_idx+=len;
        }
        
        //确保可写空间足够(整体空闲空间)
        void EnsureWriteSpace(uint64_t len)
        {
            if(TailIdleSize()>=len) return;
            //末尾空间不够
            if(len<=TailIdleSize()+HeadIdleSize())
            {
                //移动数据到起始位置
                uint64_t rsz = ReadAbleSize();
                std::copy(ReadPosition(),ReadPosition()+rsz,Begin());//把可读数据拷贝到起始位置
                _reader_idx=0;
                _writer_idx = rsz;
            }
            else
            {
                //总体空间不够,扩容->不移动数据,给写偏移后面进行扩容
                DLOG("Resize %ld",_writer_idx+len);
                _buffer.resize(_writer_idx+len);
            }
        }

        //写入数据
        void Write(const void * data,uint64_t len)
        {
            if(len == 0) return;
            EnsureWriteSpace(len);
            const char * d = (const char*)data;
            std::copy(d,d+len,WritePosition());
        }

        //写入数据+移动写入指针
        void WriteAndPush(const void * data,uint64_t len)
        {
            Write(data,len);
            MoveWriteOffset(len);
        }

        //写入字符串
        void WriteString(const std::string & data)
        {
            return Write(data.c_str(),data.size());
        }

        //写入字符串+移动写入指针
        void WriteStringAndPush(const std::string & data)
        {
            WriteString(data);
            MoveWriteOffset(data.size());
        }

        //写入缓冲区内容
        void WriteBuffer(Buffer & data)
        {
            return Write(data.ReadPosition(),data.ReadAbleSize());
        }

        //写入缓冲区内容+移动写入指针
        void WriteBufferAndPush(Buffer & data)
        {
            WriteBuffer(data);
            MoveWriteOffset(data.ReadAbleSize());
        }

        //读取数据
        void Read(void * buf,uint64_t len)
        {
            //要获取的数据大小必须小于可读数据大小
            assert(len<=ReadAbleSize());
            std::copy(ReadPosition(),ReadPosition()+len,(char*)buf);
        }

        //读取数据+移动读取指针
        void ReadAndPop(void * buf,uint64_t len)
        {
            Read(buf,len);
            MoveReadOffset(len);
        }

        //读取数据,返回字符串
        std::string ReadAsString(uint64_t len)
        {
            //要获取的数据大小必须小于可读数据大小
            assert(len<=ReadAbleSize());
            std::string str;
            str.resize(len);
            Read(&str[0],len);
            return str;
        }

        //读取数据,返回字符串+移动读取指针
        std::string ReadAsStringAndPop(uint64_t len)
        {
            std::string str = ReadAsString(len);
            MoveReadOffset(len);
            return str;
        }

        //读取一行,以\n作为结束
        char * FindCRLF()
        {
            char * res = (char*)memchr(ReadPosition(),'\n',ReadAbleSize());
            return res;
        }

        //读取一行,返回字符串
        std::string GetLine()
        {
            char * pos = FindCRLF();
            if(pos == nullptr) return "";
            return ReadAsString(pos-ReadPosition()+1);//+1读取出\n
        }

        //读取一行,返回字符串+移动读取指针
        std::string GetLineAndPop()
        {
            std::string str = GetLine();
            MoveReadOffset(str.size());
            return str;
        }

        //清空缓冲区->只需要将偏移量归零
        void Clear()
        {
            _reader_idx = 0;
            _writer_idx = 0;
        }

    private:
        std::vector<char> _buffer;//使用vector进行内存空间管理
        uint64_t _reader_idx;//读偏移->相对_buffer起始地址的偏移量
        uint64_t _writer_idx;//写偏移->相对_buffer起始地址的偏移量
    };
}